package cn.jiangzeyin.job;

import cn.jiangzeyin.entity.CacheJobInfo;
import cn.jiangzeyin.entity.IQuartzInfo;
import cn.jiangzeyin.log.JobLog;
import cn.jiangzeyin.system.SystemJobManager;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;

import java.util.List;
import java.util.Properties;

/**
 * 调度信息工具类
 *
 * @author jiangzeyin
 */
public final class JobUtil {
    private static final StdSchedulerFactory STD_SCHEDULER_FACTORY = new StdSchedulerFactory();
    private volatile static Scheduler scheduler = null;


    /**
     * @return 对象
     * @throws SchedulerException 异常
     * @author jiangzeyin
     */
    public static Scheduler getScheduler() throws SchedulerException {
        // 通过schedulerFactory获取一个调度器
        if (scheduler == null) {
            synchronized (JobUtil.class) {
                if (scheduler == null) {
                    Properties props = new Properties();
                    // props.put(StdSchedulerFactory.PROP_SCHED_INSTANCE_NAME, SystemCache.systemTag);
                    props.put(StdSchedulerFactory.PROP_SCHED_MAX_BATCH_SIZE, 50 + "");
                    // 线程池大小
                    String propThreadPoolPrefix = StdSchedulerFactory.PROP_THREAD_POOL_PREFIX + ".threadCount";
                    props.put(propThreadPoolPrefix, 500 + "");
                    STD_SCHEDULER_FACTORY.initialize(props);
                    scheduler = STD_SCHEDULER_FACTORY.getScheduler();
                }
            }
        }
        return scheduler;
    }

    /**
     * 获取调度时间信息
     *
     * @param group 组
     * @param id    id
     * @return trigger
     * @throws SchedulerException 异常
     * @author jiangzeyin
     */
    private static Trigger getTrigger(String group, int id) throws SchedulerException {
        TriggerKey key = new TriggerKey(getTriggerName(group, id), group);
        Scheduler scheduler = getScheduler();
        return scheduler.getTrigger(key);
    }

    public static Trigger getTrigger(String group, String name) throws SchedulerException {
        TriggerKey key = new TriggerKey(name, group);
        Scheduler scheduler = getScheduler();
        return scheduler.getTrigger(key);
    }

    /**
     * 获取调度状态
     *
     * @param group 组
     * @param id    id
     * @return 结果
     * @throws SchedulerException 异常
     * @author jiangzeyin
     */
    public static Trigger.TriggerState getTriggerState(String group, int id) throws SchedulerException {
        TriggerKey key = new TriggerKey(getTriggerName(group, id), group);
        Scheduler scheduler = getScheduler();
        return scheduler.getTriggerState(key);
    }

    private static String getTriggerName(String group, int id) {
        return String.format("trigger_%s_%d", group, id);
    }

    /**
     * 获取job 全局唯一的key
     *
     * @param iQuartzInfo 数据接口对象
     * @return key
     */
    public static String getJobKeyName(IQuartzInfo iQuartzInfo) {
        return String.format("%s_%d", iQuartzInfo.getGroupName(), iQuartzInfo.getId());
    }

    /**
     * 添加调度
     *
     * @param quartz 接口对象
     * @throws ClassNotFoundException 异常1
     * @throws SchedulerException     异常2
     */
    public static void addQuartz(IQuartzInfo quartz) throws ClassNotFoundException, SchedulerException {
        // 判断是否是调试
        String key = getJobKeyName(quartz);
        if (SystemJobManager.isDebug()) {
            // 判断是否为调试模式
            List<String> deBugList = SystemJobManager.getDeBugList();
            if (deBugList == null) {
                JobLog.getInstance().info("没有正确的配置调试参数");
                return;
            }
            if (!deBugList.contains(key)) {
                JobLog.getInstance().info("当前为调试环境，不能运行" + quartz.getName());
                return;
            }
        }
        List<String> stand = SystemJobManager.getStandAloneList();
        if (stand != null) {
            if (!stand.contains(key)) {
                JobLog.getInstance().info("当前为单机运行，不能运行" + quartz.getName());
                return;
            }
        }
        if (SystemJobListening.containsQuartzInfo(key)) {
            throw new RuntimeException(key + " 已经创建啦");
        }
        Trigger old_trigger = getTrigger(quartz.getGroupName(), quartz.getId());
        if (old_trigger != null) {
            JobLog.getInstance().info(quartz.getName() + " 已经存在调度信息");
            return;
        }
        Scheduler scheduler = getScheduler();
        Class<? extends Job> cls = (Class<? extends Job>) Class.forName(quartz.getRunClass());

        // 处理调度data
        JobDataMap dataMap = new JobDataMap();
        dataMap.put("id", quartz.getId());
        dataMap.put("name", quartz.getName());

        // 创建调度任务信息
        JobDetail job = JobBuilder//
                .newJob(cls)//
                .withIdentity(key, quartz.getGroupName())//
                .usingJobData(dataMap)//
                .storeDurably(true)//
                .requestRecovery(true)//
                .build();

        // 创建调度触发器信息
        CronTrigger trigger = TriggerBuilder//
                .newTrigger()//
                .withIdentity(getTriggerName(quartz.getGroupName(), quartz.getId()), quartz.getGroupName())//
                .withSchedule(CronScheduleBuilder.cronSchedule(quartz.getCron())).build();
        scheduler.scheduleJob(job, trigger);

        // 添加到任务列表
        CacheJobInfo job_ = new CacheJobInfo();
        job_.setId(quartz.getId());
        job_.setTrigger(trigger);
        job_.setJob(job);
        job_.setKey(key);
        job_.setRunClass(quartz.getRunClass());
        job_.setCron(quartz.getCron());
        job_.setStatus(quartz.getStatus());
        job_.setName(quartz.getName());
        SystemJobListening.putRunJobInfo(job_);
        if (JobUtil.optQuartz != null) {
            JobUtil.optQuartz.add(quartz);
        }
        JobLog.getInstance().info(quartz.getName() + " 加载完成:" + trigger.getStartTime().toString());

    }

    /**
     * 删除任务
     *
     * @param detailKey key
     * @param triggKey  key
     * @throws Exception 异常
     */
    public static void deleteJob(JobKey detailKey, TriggerKey triggKey) throws Exception {
        Scheduler sched = getScheduler();
        // 清理触发器
        sched.pauseTrigger(triggKey);
        sched.unscheduleJob(triggKey);
        // 清理任务
        sched.pauseJob(detailKey);
        sched.deleteJob(detailKey);
        JobLog.getInstance().info("删除调度：" + detailKey.toString());
    }

    /**
     * 暂停任务
     *
     * @param key      key
     * @param triggKey key
     * @throws Exception 异常
     */
    public static void pauseJob(JobKey key, TriggerKey triggKey) throws Exception {
        Scheduler sched = getScheduler();
        sched.pauseJob(key);
        sched.pauseTrigger(triggKey);
        JobLog.getInstance().info("暂停调度：" + key.toString());
    }

    /**
     * 恢复任务
     *
     * @param key      key
     * @param triggKey key
     * @throws Exception 异常
     */
    public static void resumeJob(JobKey key, TriggerKey triggKey) throws Exception {
        Scheduler scheduler = getScheduler();
        scheduler.resumeJob(key);
        scheduler.resumeTrigger(triggKey);
        JobLog.getInstance().info("恢复调度：" + key.toString());
    }

    private static IOptQuartz optQuartz;

    public static void setOptQuartz(IOptQuartz optQuartz) {
        JobUtil.optQuartz = optQuartz;
    }

    /**
     * 操作回调
     */
    public interface IOptQuartz {
        /**
         * 添加
         *
         * @param iQuartzInfo quartz
         */
        void add(IQuartzInfo iQuartzInfo);
    }
}
